package com.gitee.candy.utils;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class LikeSearch {
    private ConcurrentHashMap<Integer, Set<Integer>> indexMap = new ConcurrentHashMap();
    private List<String> dataList = new ArrayList<>();
    private ConcurrentHashMap<String, Integer> dataMap = new ConcurrentHashMap();

    public List<String> search(String key) {
        char[] chars = key.toCharArray();
        Integer length = chars.length;
        Context context = new Context();
        for (int i = 0; i < length; i++) {
            Set<Integer> set = indexMap.get(Integer.valueOf(chars[i]));
            context.filter(set);
        }
        ArrayList<String> result = new ArrayList<>();
        if (context.set != null) {
            for (Integer integer : context.set) {
                result.add(dataList.get(integer));
            }
        }
        return result;
    }

    public void add(String key) {
        dataList.add(key);
        Integer index = dataList.size() - 1;
        dataMap.put(key, index);
        char[] chars = key.toCharArray();
        for (char c : chars) {
            Set<Integer> set = indexMap.get(Integer.valueOf(c));
            if (set == null) {
                set = new HashSet<>();
            }
            set.add(index);
            indexMap.put(Integer.valueOf(c), set);
        }
    }

    public void remove(String key) {
        char[] chars = key.toCharArray();
        if (dataMap.containsKey(key)) {
            dataList.set(dataMap.get(key), "");
            for (char c : chars) {
                Set<Integer> set = indexMap.get(Integer.valueOf(c));
                set.remove(dataMap.get(key));
            }
        }
    }

    private class Context {
        Set<Integer> set;

        public void filter(Set<Integer> targetSet) {
            if (this.set == null) {
                this.set = targetSet;
            } else {
                Set<Integer> mixedSet = new HashSet<>();
                for (Integer integer : set) {
                    if (targetSet.contains(integer)) {
                        mixedSet.add(integer);
                    }
                }
                this.set = mixedSet;
            }
        }
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        LikeSearch search = new LikeSearch();
        search.add("湖南");
        search.add("湖北");
        search.add("河南");
        search.add("河北");

        System.out.println(search.search("湖"));
        System.out.println(search.search("河"));
        System.out.println(search.search("北"));
        System.out.println(search.search("南"));
        System.out.println(search.search("suyl"));
        System.out.println("======================");
        System.out.println(search.dataList);
        System.out.println(search.dataMap);
        System.out.println(search.indexMap);
    }
}
